home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvipage / findfile.c < prev    next >
C/C++ Source or Header  |  1992-05-11  |  10KB  |  504 lines

  1. /*
  2.  * dvipage: DVI Previewer Program for Suns
  3.  *
  4.  * Neil Hunt (hunt@spar.slb.com)
  5.  *
  6.  * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
  7.  * Anyone can use this software in any manner they choose,
  8.  * including modification and redistribution, provided they make
  9.  * no charge for it, and these conditions remain unchanged.
  10.  *
  11.  * This program is distributed as is, with all faults (if any), and
  12.  * without any warranty. No author or distributor accepts responsibility
  13.  * to anyone for the consequences of using it, or for whether it serves any
  14.  * particular purpose at all, or any other reason.
  15.  *
  16.  * $Log:    findfile.c,v $
  17.  * Revision 1.1  88/11/28  18:40:44  hunt
  18.  * Initial revision
  19.  * 
  20.  * Based upon `mitdrivers/findfile.c'
  21.  * Copyright 1985 Massachusetts Institute of Technology
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <sys/types.h>
  26. #include <sys/dir.h>
  27. #include <sys/file.h>
  28. #include <sys/param.h>        /* For MAXPATHLEN */
  29. #include <suntool/sunview.h>
  30. #include "dvipage.h"
  31.  
  32. forward bool    find_file_in_path();
  33. forward bool    find_best_file_in_path();
  34. forward bool    scandir();
  35. forward bool    scanpdir();
  36. forward int    strdiff();
  37.  
  38.  
  39. /*
  40.  * find_file:
  41.  *    Seaches for a font file in various places.
  42.  *    dirpath is a colon separated list of possible pathnames.
  43.  *    Returns TRUE if a usable file was found.
  44.  */
  45.  
  46. bool find_font_file(dir_path, fontptr)
  47. char *dir_path;
  48. struct font_entry *fontptr;
  49. {
  50.     int min_df, min_dp, min_dm;
  51.  
  52.     if(verbose & DEBUG_FONTS)
  53.         fprintf(stderr, "find_font_file(%s .%dgf or .%dpxl)\n",
  54.           fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
  55.  
  56.     /*
  57.      * Search for exact match.
  58.      */
  59.     if(find_file_in_path(dir_path, fontptr))
  60.         return TRUE;
  61.  
  62.     /*
  63.      * Search for nearest match.
  64.      */
  65.     min_df = min_dp = min_dm = MAXINT;
  66.     if(find_best_file_in_path(dir_path, fontptr,
  67.       &min_df, &min_dp, &min_dm))
  68.     {
  69.         message("Substituted font %s for %s.%d.",
  70.           fontptr->name, fontptr->n, fontptr->type == TYPE_PXL ?
  71.           fontptr->font_pxl_mag : fontptr->font_gf_mag);
  72.         return TRUE;
  73.     }
  74.  
  75.     return FALSE;
  76. }
  77.  
  78. /*
  79.  * find_file_in_path:
  80.  *    Searches path for a font file.
  81.  *    Returns TRUE if a suitable match has been found.
  82.  */
  83.  
  84. bool
  85. find_file_in_path(dirpath, fontptr)
  86. char *dirpath;
  87. struct font_entry *fontptr;
  88. {
  89.     char *p;
  90.     char dir[MAXPATHLEN];
  91.  
  92.     while(*dirpath)
  93.     {
  94.         /*
  95.          * Copy first/next path prefix to dir[].
  96.          * Skip over the ':'.
  97.          */
  98.         for(p = dir; *dirpath; )
  99.         {
  100.             if(*dirpath == ':' || *dirpath == ';')
  101.             {
  102.                 dirpath++;
  103.                 break;
  104.             }
  105.             else
  106.                 *p++ = *dirpath++;
  107.         }
  108.         *p = '\0';
  109.  
  110.         if(use_pk)
  111.         {
  112.             /*
  113.              * Try flat structure.
  114.              */
  115.             sprintf(fontptr->name, "%s/%s.%dpk",
  116.               dir, fontptr->n, fontptr->font_gf_mag);
  117.             if(access(fontptr->name, R_OK) == 0)
  118.             {
  119.                 if(verbose & DEBUG_FONTS)
  120.                     fprintf(stderr, " Try %s; OK\n",
  121.                       fontptr->name);
  122.                 fontptr->type = TYPE_PK;
  123.                 return TRUE;
  124.             }
  125.             else
  126.             {
  127.                 if(verbose & DEBUG_FONTS)
  128.                     fprintf(stderr, " Try %s; No\n",
  129.                       fontptr->name);
  130.             }
  131.  
  132.             /*
  133.              * Try hierarchical structure.
  134.              */
  135.             sprintf(fontptr->name, "%s/%s/%s.%dpk",
  136.               dir, fontptr->n, fontptr->n, fontptr->font_gf_mag);
  137.             if(access(fontptr->name, R_OK) == 0)
  138.             {
  139.                 if(verbose & DEBUG_FONTS)
  140.                     fprintf(stderr, " Try %s; OK\n",
  141.                       fontptr->name);
  142.                 fontptr->type = TYPE_PK;
  143.                 return TRUE;
  144.             }
  145.             else
  146.             {
  147.                 if(verbose & DEBUG_FONTS)
  148.                     fprintf(stderr, " Try %s; No\n",
  149.                       fontptr->name);
  150.             }
  151.         }
  152.  
  153.         if(use_gf)
  154.         {
  155.             /*
  156.              * Try flat structure.
  157.              */
  158.             sprintf(fontptr->name, "%s/%s.%dgf",
  159.               dir, fontptr->n, fontptr->font_gf_mag);
  160.             if(access(fontptr->name, R_OK) == 0)
  161.             {
  162.                 if(verbose & DEBUG_FONTS)
  163.                     fprintf(stderr, " Try %s; OK\n",
  164.                       fontptr->name);
  165.                 fontptr->type = TYPE_GF;
  166.                 return TRUE;
  167.             }
  168.             else
  169.             {
  170.                 if(verbose & DEBUG_FONTS)
  171.                     fprintf(stderr, " Try %s; No\n",
  172.                       fontptr->name);
  173.             }
  174.  
  175.             /*
  176.              * Try hierarchical structure.
  177.              */
  178.             sprintf(fontptr->name, "%s/%s/%s.%dgf",
  179.               dir, fontptr->n, fontptr->n, fontptr->font_gf_mag);
  180.             if(access(fontptr->name, R_OK) == 0)
  181.             {
  182.                 if(verbose & DEBUG_FONTS)
  183.                     fprintf(stderr, " Try %s; OK\n",
  184.                       fontptr->name);
  185.                 fontptr->type = TYPE_GF;
  186.                 return TRUE;
  187.             }
  188.             else
  189.             {
  190.                 if(verbose & DEBUG_FONTS)
  191.                     fprintf(stderr, " Try %s; No\n",
  192.                       fontptr->name);
  193.             }
  194.         }
  195.  
  196.         if(use_pxl)
  197.         {
  198.             /*
  199.              * Try flat structure.
  200.              */
  201.             sprintf(fontptr->name, "%s/%s.%dpxl",
  202.               dir, fontptr->n, fontptr->font_pxl_mag);
  203.             if(access(fontptr->name, R_OK) == 0)
  204.             {
  205.                 if(verbose & DEBUG_FONTS)
  206.                     fprintf(stderr, " Try %s; OK\n",
  207.                       fontptr->name);
  208.                 fontptr->type = TYPE_PXL;
  209.                 return TRUE;
  210.             }
  211.             else
  212.             {
  213.                 if(verbose & DEBUG_FONTS)
  214.                     fprintf(stderr, " Try %s; No\n",
  215.                       fontptr->name);
  216.             }
  217.  
  218.             /*
  219.              * Try hierarchical structure.
  220.              */
  221.             sprintf(fontptr->name, "%s/%s/%s.%dpxl",
  222.               dir, fontptr->n, fontptr->n, fontptr->font_pxl_mag);
  223.             if(access(fontptr->name, R_OK) == 0)
  224.             {
  225.                 if(verbose & DEBUG_FONTS)
  226.                     fprintf(stderr, " Try %s; OK\n",
  227.                       fontptr->name);
  228.                 fontptr->type = TYPE_PXL;
  229.                 return TRUE;
  230.             }
  231.             else
  232.             {
  233.                 if(verbose & DEBUG_FONTS)
  234.                     fprintf(stderr, " Try %s; No\n",
  235.                       fontptr->name);
  236.             }
  237.         }
  238.     }
  239.  
  240.     return FALSE;
  241. }
  242.  
  243. /*
  244.  * find_best_file_in_path:
  245.  *    Finds the best match to the desired font.
  246.  *    Returns TRUE if a suitable match is found.
  247.  */
  248.  
  249. bool
  250. find_best_file_in_path(dirpath, fontptr, p_min_df, p_min_dp, p_min_dm)
  251. char *dirpath;
  252. struct font_entry *fontptr;
  253. int *p_min_df, *p_min_dp, *p_min_dm;
  254. {
  255.     register char *p;
  256.     char dir[MAXPATHLEN];
  257.     bool status = FALSE;
  258.  
  259.     if(verbose & DEBUG_FONTS)
  260.         fprintf(stderr, "find_best_font_file(%s .%dgf or %dpxl)\n",
  261.           fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
  262.  
  263.     /*
  264.      * Scan over directories in dirpath.
  265.      */
  266.     while(*dirpath)
  267.     {
  268.         /*
  269.          * Copy first/next path prefix to dir[].
  270.          * Skip over the ':'.
  271.          */
  272.         for(p = dir; *dirpath != '\0'; )
  273.         {
  274.             if(*dirpath == ':' || *dirpath == ';')
  275.             {
  276.                 dirpath++;
  277.                 break;
  278.             }
  279.             else
  280.                 *p++ = *dirpath++;
  281.         }
  282.         *p = '\0';
  283.  
  284.         /*
  285.          * Scan the directory.
  286.          */
  287.         if(scanpdir(dir, fontptr, p_min_df, p_min_dp, p_min_dm))
  288.             status = TRUE;
  289.  
  290.         /*
  291.          * Scan any subdirectories.
  292.          */
  293.         if(scandir(dir, fontptr, p_min_df, p_min_dp, p_min_dm))
  294.             status = TRUE;
  295.     }
  296.  
  297.     return status;
  298. }
  299.  
  300. /*
  301.  * scandir:
  302.  *    Scan directory looking for plausible names,
  303.  *    then recurse to subdirectories for plausible point sizes.
  304.  *    Returns TRUE if found a more plausible candidate than previous best.
  305.  */
  306.  
  307. bool
  308. scandir(dir, fontptr, p_min_df, p_min_dp, p_min_dm)
  309. char *dir;
  310. struct font_entry *fontptr;
  311. int *p_min_df, *p_min_dp, *p_min_dm;
  312. {
  313.     DIR *dirstream;
  314.     struct direct *dirrecord;
  315.     char pdir[MAXPATHLEN];
  316.     bool status = FALSE;
  317.  
  318.     if(verbose & DEBUG_FONTS)
  319.         fprintf(stderr, " scandir(%s .%dgf or .%dpxl)\n",
  320.           fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
  321.  
  322.     if(! (dirstream = opendir(dir)))
  323.         return FALSE;
  324.  
  325.     while(dirrecord = readdir(dirstream))
  326.     {
  327.         if(dirrecord->d_name[0] != '.')
  328.             continue;
  329.  
  330.         if(strdiff(fontptr->n, dirrecord->d_name) <= *p_min_df)
  331.         {
  332.             sprintf(pdir, "%s/%s", dir, dirrecord->d_name);
  333.  
  334.             if(scanpdir(pdir, fontptr,
  335.               p_min_df, p_min_dp, p_min_dm))
  336.                 status = TRUE;
  337.         }
  338.     }
  339.  
  340.     closedir(dirstream);
  341.  
  342.     return status;
  343. }
  344.  
  345. /*
  346.  * scanpdir:
  347.  *    Scan directory looking for plausible names and point sizes.
  348.  *    Returns TRUE if found a more plausible candidate than previous best.
  349.  */
  350.  
  351. bool
  352. scanpdir(dir, fontptr, p_min_df, p_min_dp, p_min_dm)
  353. char *dir;
  354. struct font_entry *fontptr;
  355. int *p_min_df, *p_min_dp, *p_min_dm;
  356. {
  357.     DIR *dirstream;
  358.     struct direct *dirrecord;
  359.     char qfamily[MAXPATHLEN];
  360.     char qtype[MAXPATHLEN];
  361.     int qpoint, qmag, df, dp, dm;
  362.     bool status = FALSE;
  363.     char family[MAXPATHLEN];
  364.     int point;
  365.  
  366.     if(verbose & DEBUG_FONTS)
  367.         fprintf(stderr, " scanpdir(%s .%dgf or .%dpxl)\n",
  368.           fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
  369.  
  370.     /*
  371.      * Split out family name, point size and magnification.
  372.      */
  373.     if(sscanf(fontptr->n, "%[^0123456789.]%d", family, &point) != 2)
  374.     {
  375.         message("Font name \"%s\" appears garbled.", fontptr->n);
  376.         return FALSE;
  377.     }
  378.  
  379.     if(! (dirstream = opendir(dir)))
  380.         return FALSE;
  381.  
  382.     while(dirrecord = readdir(dirstream))
  383.     {
  384.         if(sscanf(dirrecord->d_name, "%[^0123456789.]%d.%d%s",
  385.           qfamily, &qpoint, &qmag, qtype) != 4)
  386.             continue;
  387.  
  388.         /*
  389.          * Is this a GF file.
  390.          */
  391.         if(use_gf && strcmp(qtype, "gf") == 0)
  392.         {
  393.             df = strdiff(family, qfamily);
  394.             dp = abs(point - qpoint);
  395.             dm = abs(fontptr->font_gf_mag - qmag);
  396.             if((df < *p_min_df) ||
  397.                (df == *p_min_df && dp < *p_min_dp) ||
  398.                (df == *p_min_df && dp == *p_min_dp &&
  399.                  dm < *p_min_dm))
  400.             {
  401.                 *p_min_df = df;
  402.                 *p_min_dp = dp;
  403.                 *p_min_dm = dm;
  404.  
  405.                 sprintf(fontptr->name, "%s/%s",
  406.                   dir, dirrecord->d_name);
  407.                 fontptr->type = TYPE_GF;
  408.  
  409.                 if(verbose & DEBUG_FONTS)
  410.                     fprintf(stderr,
  411.                       "  New best match (%d %d %d) is %s\n",
  412.                       df, dp, dm, fontptr->name);
  413.  
  414.                 status = TRUE;
  415.             }
  416.         }
  417.  
  418.         /*
  419.          * Is this a PXL file.
  420.          */
  421.         if(use_pxl && strcmp(qtype, "pxl") == 0)
  422.         {
  423.             df = strdiff(family, qfamily);
  424.             dp = abs(point - qpoint);
  425.             dm = abs(fontptr->font_pxl_mag - qmag);
  426.             if((df < *p_min_df) ||
  427.                (df == *p_min_df && dp < *p_min_dp) ||
  428.                (df == *p_min_df && dp == *p_min_dp &&
  429.                  dm < *p_min_dm))
  430.             {
  431.                 *p_min_df = df;
  432.                 *p_min_dp = dp;
  433.                 *p_min_dm = dm;
  434.  
  435.                 sprintf(fontptr->name, "%s/%s",
  436.                   dir, dirrecord->d_name);
  437.                 fontptr->type = TYPE_PXL;
  438.  
  439.                 if(verbose & DEBUG_FONTS)
  440.                     fprintf(stderr,
  441.                       "  New best match (%d %d %d) is %s\n",
  442.                       df, dp, dm, fontptr->name);
  443.  
  444.                 status = TRUE;
  445.             }
  446.         }
  447.  
  448.         /*
  449.          * Is this a PK file.
  450.          */
  451.         if(use_pk && strcmp(qtype, "pk") == 0)
  452.         {
  453.             df = strdiff(family, qfamily);
  454.             dp = abs(point - qpoint);
  455.             dm = abs(fontptr->font_gf_mag - qmag);
  456.             if((df < *p_min_df) ||
  457.                (df == *p_min_df && dp < *p_min_dp) ||
  458.                (df == *p_min_df && dp == *p_min_dp &&
  459.                  dm < *p_min_dm))
  460.             {
  461.                 *p_min_df = df;
  462.                 *p_min_dp = dp;
  463.                 *p_min_dm = dm;
  464.  
  465.                 sprintf(fontptr->name, "%s/%s",
  466.                   dir, dirrecord->d_name);
  467.                 fontptr->type = TYPE_PK;
  468.  
  469.                 if(verbose & DEBUG_FONTS)
  470.                     fprintf(stderr,
  471.                       "  New best match (%d %d %d) is %s\n",
  472.                       df, dp, dm, fontptr->name);
  473.  
  474.                 status = TRUE;
  475.             }
  476.         }
  477.     }
  478.  
  479.     closedir(dirstream);
  480.  
  481.     return status;
  482. }
  483.  
  484. /*
  485.  * strdiff:
  486.  *    Quantify differences in font names.
  487.  */
  488.  
  489. int 
  490. strdiff(s1, s2)
  491. char *s1, *s2;
  492. {
  493.     register int diff = 0;
  494.  
  495.     while(*s1 && *s2)
  496.         diff += abs(*s1++ - *s2++);
  497.     while(*s1)
  498.         diff += *s1++;
  499.     while(*s2)
  500.         diff += *s2++;
  501.  
  502.     return diff;
  503. }
  504.